import axios, {
  AxiosHeaderValue,
  AxiosRequestConfig,
  AxiosRequestHeaders,
  ResponseType
} from 'axios'

import { getToken } from '@/utils'
import { message } from 'antd'

// create an axios instance
const service = axios.create({
  // baseURL: process.env.NODE_ENV === 'development' ? '' : ('./' + import.meta.env.VITE_APP_NAME), // url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  timeout: 30000 // request timeout
})

// request interceptor
service.interceptors.request.use(
  (config) => {
    return config
  },
  (error) => {
    // do something with request error
    console.log(error) // for debug
    return Promise.reject(error)
  }
)

// response interceptor
service.interceptors.response.use(
  /**
   * If you want to get http information such as headers or status
   * Please return  response => response
   */

  /**
   * Determine the request status by custom code
   * Here is just an example
   * You can also judge the status by HTTP Status Code
   */
  (response) => {
    const res = response.data
    if (response.headers['content-type'] === 'text/xml') {
      return response
    }
    if (
      response.headers['content-type'].includes('application/octet-stream') ||
      response.headers['content-type'].includes('application/vnd.ms-excel')
    ) {
      console.log('responseheaders')
      const content: string = response.headers['content-disposition']
      const contarr: Array<string> = content.split(';')
      const downloadFileData = {
        fileName: '',
        blob: ''
      }
      contarr.map((item, index) => {
        if (item.indexOf('filename=') > -1) {
          const filename = item.split('=')[1]

          downloadFileData.fileName = decodeURIComponent(filename)
        }
      })
      downloadFileData.blob = response.data
      response.data = downloadFileData
      return response
    }

    // if the custom code is not 20000, it is judged as an error.
    // console.log(res)
    if (res.code !== 0 && res.code !== 3004) {
      message.destroy()

      message.error(
        res.msg || res.message || '接口调用错误，请联系管理员',
        5 * 1000
      )

      // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
      if (res.code === 4003) {
        localStorage.removeItem('token')
      } else if (res.code === 4100) {
        localStorage.removeItem('token')
        if (!window.location.href.includes('/login')) {
          goLogin()
        }
      }
      return Promise.reject(new Error(res.message || 'Error'))
    } else {
      return res
    }
  },
  (error) => {
    message.destroy()
    message.error(error.message || error.msg, 5 * 1000)
    return Promise.reject(error)
  }
)

type RequertConfig = AxiosRequestConfig & {
  option?: { header?: AxiosRequestHeaders }
}

function goLogin() {
  window.location.href = '/login'
}

const request = <T>(
  config: RequertConfig
): Promise<[Error | null, T | null]> => {
  const token: AxiosHeaderValue = getToken() || ''
  const auth: AxiosRequestHeaders & any = {}
  Object.assign(auth, {
    Authorization: token
  })
  // debugger
  if (!config.url?.includes('/login')) {
    if (!token) {
      goLogin()
    }
  } else if (!config.url.includes('/getRouter')) {
    Object.assign(auth, {})
  }

  const conf: AxiosRequestConfig = { url: config.url, method: config.method }
  if (conf.method === 'GET' || conf.method === 'get') {
    conf.params = config.data || ''
  } else {
    conf.data = config.data
  }
  //让 responseType 生效
  if (config.responseType) {
    conf.responseType = config.responseType
  }
  if (config.option && config.option.header) {
    conf.headers = {
      ...config.option.header,
      ...auth
    }
  } else if (conf.method === 'POST' || conf.method === 'post') {
    conf.headers = {
      'Content-Type': 'application/json',
      ...auth
    }
  } else {
    conf.headers = {
      ...auth
    }
  }
  if (config.timeout !== undefined) {
    conf.timeout = config.timeout
  }
  return service
    .request(conf)
    .then<[null, T]>((res) => [null, res.data])
    .catch<[Error, null]>((err) => [err, null])
}
export default request
